package com.matt.service.impl;

import com.fasterxml.jackson.databind.JavaType;
import com.matt.commons.dto.sso.StaffDTO;
import com.matt.domain.*;
import com.matt.foundation.annotation.OptsTrace;
import com.matt.foundation.constant.*;
import com.matt.foundation.dto.teach.ProductDTO;
import com.matt.commons.exception.BusinessException;
import com.matt.foundation.model.ErrorCode;
import com.matt.foundation.model.StatusResponse;
import com.matt.foundation.query.ContractQuery;
import com.matt.foundation.utils.CopyUtils;
import com.matt.foundation.utils.DateUtil;
import com.matt.foundation.utils.ModelUtil;
import com.matt.foundation.vo.*;
import com.matt.remoteCall.SsoCallService;
import com.matt.repository.*;
import com.matt.repository.base.ContractNativeRepository;
import com.matt.repository.base.ContractProductNativeRepository;
import com.matt.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static com.matt.foundation.constant.OperateConstant.OPERATE_CREATE;
import static com.matt.foundation.constant.ProductConstant.EARLY;


/**
 * ************************
 * Created by Ron
 * from com.matt
 * on 2018/6/14 0014.
 * ***********************
 */
@Service
@Slf4j
public class ContractServiceImpl implements ContractService {
    @Autowired
    private ContractRepository contractRepository;
    @Autowired
    private LeadsRepository leadsRepository;
    @Autowired
    private ClienteleRepository clienteleRepository;
    @Autowired
    private ContractNativeRepository contractNativeRepository;
    @Autowired
    private ContractProductRepository contractProductRepository;
    @Autowired
    private ContractProductNativeRepository contractProductNativeRepository;

    @Autowired
    private ProductRepository productRepository;

    @Autowired
    private AnalysisService analysisService;

    @Autowired
    private TeachCallService teachCallService;

    @Autowired
    private ClienteleService clienteleService;

    @Autowired
    private ContractHistoryRepository contractHistoryRepository;
    
    @Autowired
    private ContractFreezeRepository contractFreezeRepository;


    @Transactional
    @OptsTrace(code = "20004")
    @Override
    public Contract save(StaffDTO staff, Contract contract, String productRecords) {
        Date today = new Date();

//        StaffDTO baseInfo = ssoCallService.getStaffDTO(ticket);
//        StaffDTO staff = ssoCallService.getStaffDTO(ticket);
        contract.setAreaId(staff.getAreaId());
        contract.setStaffId(staff.getId());
        contract.setStaffName(staff.getRealName());
        contract.setLastModified(today);
        contract.setLastModifiedId(staff.getId());
        contract.setIsRenewal(contractRepository.findByClienteleId(contract.getClienteleId()).size() > 0);
        Clientele clientele = clienteleRepository.getOne(contract.getClienteleId());
        if (clientele == null || clientele.getBirthday() == null) {
            throw new BusinessException(ErrorCode.CLIENTELE_BIRRHDAY_NULL, "客户/出生年月必填，请先完善客户信息");
        }

        //修改客户的成交状态
        clientele.setSignStatus(ClienteleConstant.SignStatus.SIGN.codeOf());

        //处理合同的付款状态
        if(contract.getPayType() == 2){
            contract.setPayStatus(ContractConstant.PayStatus.PAID.codeOf());
            contract.setPayStatusVal(ContractConstant.PayStatus.PAID.valueOf());
        }

        contractRepository.save(contract);

        //如果不是续约合同
        if (!contract.getIsRenewal() ) {

            //教务系统生成宝宝数据
            teachCallService.addChild(clientele.getId(), clientele.getChildName(), clientele.getNickName(), clientele.getGender(),
                    DateUtil.millisToDateTime(clientele.getBirthday().getTime(), "yyyy-MM-dd"), clientele.getAreaId(), clientele.getHomeAddress(),
                    clientele.getName(), clientele.getMobile(), clientele.getCompany(), clientele.getRelationship(), contract.getStaffId());

            if(StringUtils.isNotEmpty(clientele.getLeadsId())) {
                //添加例子成交统计数据
                Leads leads = leadsRepository.getOne(clientele.getLeadsId());
                if (leads != null) {
                    analysisService.deal(leads.getId(), leads.getCategory(), leads.getChannelId(), leads.getAreaId(), staff.getId(), new Date());
                }
            }
        }

        //处理合同产品及计算合同总金额
        processContractProduct(contract, productRecords, clientele.getId());
        //处理合同状态
        processContractStatus(contract, today);
        //处理教务系统逻辑
        beginTeachRoll(contract);
        //处理合同动态
        processContractCreateHistory(contract, staff.getHeadImgUrl());
        contractRepository.save(contract);
        return contract;
    }

    private void processContractProduct(Contract contract, String productRecords, String clienteleId) {
        BigDecimal totalAmount = BigDecimal.ZERO.setScale(2,BigDecimal.ROUND_HALF_DOWN);

        //反序列号
        if (contract != null && StringUtils.isNotEmpty(productRecords)) {
            List<ContractProduct> contractProducts = ModelUtil.readListFormJson(productRecords, ContractProduct.class);
            for (ContractProduct cp : contractProducts) {
                Product product = productRepository.getOne(cp.getProductId());
                if (product != null) {
                    cp.setProductType(product.getType());
                    cp.setClienteleId(clienteleId);
                    cp.setStandardAmount(product.getStandardAmount());
                    cp.setStandardTotalAmount(product.getStandardAmount().multiply(new BigDecimal(cp.getCount()).setScale(2, BigDecimal.ROUND_HALF_DOWN)));
                    cp.setPracticalTotalAmount(cp.getPracticalAmount().multiply(new BigDecimal(cp.getCount()).setScale(2, BigDecimal.ROUND_HALF_DOWN)));
                    cp.setContractId(contract.getId());
                    cp.setRemainCount(cp.getCount());//默认让剩余数量=购买数量
                    cp.setType(ContractProductConstant.Type.BUY.codeOf());//已购买产品
                    cp.setTypeVal(ContractProductConstant.Type.BUY.valueOf());
                    contract.setType(product.getType());
                    contractProductRepository.save(cp);


                    BigDecimal productCount = new BigDecimal(cp.getCount()).setScale(2, BigDecimal.ROUND_HALF_DOWN);
                    totalAmount = totalAmount.add(cp.getPracticalAmount().multiply(productCount));     //实际总价格=实际单价*数量
                    //生成续约客户
                    analysisService.renewalClientele(clienteleId, cp.getProductType());
                }
            }
            if (contractProducts.size() == 2)
                contract.setType(ProductConstant.NURSERY_EARLY);
        }
        contract.setTotalAmount(totalAmount);
        contractRepository.save(contract);
    }


    @Override
    // TODO: 支付完成需要使用这个来处理后续逻辑
    public Contract processContractStatus(Contract contract, Date today) {
        boolean isPayClear = contract.getPracticalAmount().compareTo(contract.getTotalAmount()) == 0;
        if (isPayClear) {
            contract.setPayStatus(ContractConstant.PayStatus.PAID.codeOf());
            contract.setPayStatusVal(ContractConstant.PayStatus.PAID.valueOf());
            contract.setPaidDate(today);
            if (contract.getBeginDate().compareTo(today) <= 0) {
                contract.setStatus(ContractConstant.Status.NORMAL.codeOf());//已开始
                contract.setStatusVal(ContractConstant.Status.NORMAL.valueOf());
            }
            if (contract.getBeginDate().compareTo(today) > 0) {
                contract.setStatus(ContractConstant.Status.NON_START.codeOf()); //未开始
                contract.setStatusVal(ContractConstant.Status.NON_START.valueOf());
            }
            if (contract.getEndDate().compareTo(today) < 0) {
                contract.setStatus(ContractConstant.Status.END.codeOf());
                contract.setStatusVal(ContractConstant.Status.END.valueOf());
            }
        } else {
            contract.setPayStatus(ContractConstant.PayStatus.NON_PAY.codeOf());
            contract.setPayStatusVal(ContractConstant.PayStatus.NON_PAY.valueOf());
            contract.setStatus(ContractConstant.Status.BACK_MONEY.codeOf()); //待补款
            contract.setStatusVal(ContractConstant.Status.BACK_MONEY.valueOf());
        }
        contractRepository.save(contract);
        return contract;
    }


    public void processContractCreateHistory(Contract contract, String headImgUrl) {
        //添加合同那边的操作日志
        ContractHistory contractHistory = new ContractHistory();
        contractHistory.setOperationType(OPERATE_CREATE);
        //1.定金 2.全款
        if (contract.getPayType() == ContractConstant.PayType.PART.codeOf())
            contractHistory.setContent("在 " + DateUtil.dateToymd(new Date()) + "创建了本合同 " + '\n' + " 定金 \"" + contract.getPracticalAmount() + "\" 元,待回款 \"" + contract.getTotalAmount().subtract(contract.getPracticalAmount()) + "\" 元");
        else if (contract.getPayType() == ContractConstant.PayType.ALL.codeOf())
            contractHistory.setContent("在 " + DateUtil.dateToymd(new Date()) + "创建了本合同 " + '\n' + " 全款 \"" + contract.getTotalAmount() + "\" 元");

        contractHistory.setClienteleId(contract.getClienteleId());
        contractHistory.setStaffId(contract.getStaffId());
        contractHistory.setStaffName(contract.getStaffName());
        contractHistory.setStaffHeadImgUrl(headImgUrl);
        contractHistory.setContractId(contract.getId());
        contractHistoryRepository.save(contractHistory);
    }

    public void processContractPayHistory(Contract contract, String payUser, String headImgUrl, String sourceName) {
        //添加合同那边的操作日志
        ContractHistory contractHistory = new ContractHistory();
        contractHistory.setOperationType(OPERATE_CREATE);
        //1.定金 2.全款
        String msg = "在 " + DateUtil.dateToymd(new Date()) + "将合同标记成已付款 " + '\n' + " 付款方式：" + sourceName;
        if (StringUtils.isNotBlank(payUser)){
            msg = payUser + msg;
        }
        contractHistory.setContent(msg);

        contractHistory.setClienteleId(contract.getClienteleId());
        contractHistory.setStaffId(contract.getStaffId());
        contractHistory.setStaffName(contract.getStaffName());
        contractHistory.setStaffHeadImgUrl(headImgUrl);
        contractHistory.setContractId(contract.getId());
        contractHistoryRepository.save(contractHistory);
    }

    @Override
    public Page<ContractVo> findByCondition(ContractQuery contractQuery, Pageable pageable) {
        List<ContractVo> lists = contractNativeRepository.findByConditon(contractQuery);
        Long count = contractNativeRepository.countContract(contractQuery);
        return new PageImpl<ContractVo>(lists,  PageRequest.of(contractQuery.getPageNum(), contractQuery.getPageSize()), count);
    }

    @Override
    public List<ContractExportVo> findByConditionExport(ContractQuery contractQuery) {
        contractQuery.setPageSize(999);
        List<ContractVo> lists = contractNativeRepository.findByConditon(contractQuery);
        List<ContractExportVo> exportVoList = new ArrayList<>();
        lists.stream().forEach(o->{
            ContractExportVo vo = new ContractExportVo();
            CopyUtils.copyProperties(o,vo);
            exportVoList.add(vo);
        });
        return exportVoList;
    }

    @Override
    public List<ClienteleContractVo> findContractBySyschildName(String areaId, String sysChildName) {
        List<ClienteleContractVo> list = new ArrayList<ClienteleContractVo>();
        List<Clientele> clienteles = contractNativeRepository.findContractBySyschildName(areaId, sysChildName);
        for (Clientele cli : clienteles) {
            ClienteleContractVo vo = new ClienteleContractVo();
            BeanUtils.copyProperties(cli, vo);

            List<ContractVo> contractVos = contractNativeRepository.findByClienteleId(cli.getId());
            //查询对应的产品
            for (ContractVo contractVo : contractVos) {
                // List<ContractProduct> contractProducts=contractProductRepository.findByContractId(contractVo.getId());
                List<ContractProductVo> contractProductVos = contractProductNativeRepository.findByContractId(contractVo.getId());
                contractVo.setContractProducts(contractProductVos);
            }
            vo.setContracts(contractVos);
            list.add(vo);
        }
        return list;
    }

    @OptsTrace(code = "30002")
    @Transactional
    @Override
    public Contract breakDown(StaffDTO staff, String contractId, String breakDownReason, String breakDownRemark) {
        Contract contract = contractRepository.getOne(contractId);

        if (!staff.getAreaId().equals(contract.getAreaId())){
            throw new BusinessException(ErrorCode.STAFF_HAS_NO_ROLE, "权限不够");
        }

        contract.setBreakDownReason(breakDownReason);
        contract.setBreakDownRemark(breakDownRemark);
        contract.setStatus(ContractConstant.Status.STOP.codeOf());
        contract.setStatusVal(ContractConstant.Status.STOP.valueOf());
        contractRepository.save(contract);

        return contract;
    }

    private void subtractEarlyCourse(String contractId, String clienteleId, String breakDownReason, String staffId) {
        List<ContractProduct> products = contractProductRepository.findByContractId(contractId);
        Double count = 0d;
        for (ContractProduct product : products) {
            if (product.getProductType() == EARLY)
                count += product.getRemainCount();
        }
        if (count > 0)
            teachCallService.overEarlyContract(clienteleId, ModelUtil.doubleToInt(count), breakDownReason, staffId);
    }


    @Override
    public int reduceSatNum(String clienteleId, Integer num) {
        //查询该客户已经开始、没结束的早教合同购买产品
        List<ContractProduct> contractProducts = contractProductNativeRepository.findReduceContractProducts(clienteleId);
        //循环减早教中的剩余数量，直到把传过来的数量减完
        contractProducts.get(0).setRemainCount(contractProducts.get(0).getRemainCount() - 1);
        contractProductRepository.save(contractProducts.get(0));
        return 1;
    }

    @Override
    public ContractVo details(String contractId) {
        ContractVo vo = contractNativeRepository.findById(contractId);
        List<ContractProductVo> contractProductVos = contractProductNativeRepository.findByContractId(contractId);
        vo.setContractProducts(contractProductVos);
        return vo;
    }

    @Override
    public List<Contract> contractsByClientele(String areaId, String clienteleId){
        return contractRepository.findByAreaIdAndClienteleIdOrderByCreatedDesc(areaId, clienteleId);
    }

    //2019-01-09删除
//    @Override
//    public List<Contract> findByName(String areaId, String contractTitle) {
//        List<Contract> contracts = contractRepository.findByAreaIdAndName(areaId, contractTitle);
//        return contracts;
//    }

    @OptsTrace(code = "30001")
    @Transactional
    @Override
    public Contract updateContractStaffInfo(StaffDTO operator, StaffDTO staff, String contractId) {
        Contract contract = contractRepository.getOne(contractId);
        if (!contract.getAreaId().equals(operator.getAreaId())){
            throw new BusinessException(ErrorCode.STAFF_HAS_NO_ROLE, "对象不存在");
        }
        contract.setStaffId(staff.getId());
        contract.setStaffName(staff.getRealName());
        return contractRepository.save(contract);
    }

    @Override
    public Boolean ckeckout(BigDecimal practicalAmount, String productRecords) {
        BigDecimal totalAmount = new BigDecimal("0").setScale(2, BigDecimal.ROUND_HALF_DOWN);
        //反序列号
        if (productRecords != null && !"".equals(productRecords)) {
            JavaType javaType = ModelUtil.objectMapper.getTypeFactory().constructParametricType(ArrayList.class, ContractProduct.class);
            try {
                List<ContractProduct> contractProducts = ModelUtil.objectMapper.readValue(productRecords, javaType);
                for (ContractProduct cp : contractProducts) {
//                    totalAmount = totalAmount.add(cp.getPracticalAmount().multiply(new BigDecimal(cp.getCount())));
                    BigDecimal productCount = new BigDecimal(cp.getCount()).setScale(2, BigDecimal.ROUND_HALF_DOWN);
                    totalAmount = totalAmount.add(cp.getPracticalAmount().multiply(productCount));
                }
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("json 转集合对象异常");
            }
        }
        if (practicalAmount.compareTo(totalAmount) == 1)
            return false;
        return true;
    }

    @Override
    public Boolean findByClienteleId(String clienteleId) {
        Long count = contractNativeRepository.findCountByClienteleId(clienteleId);
        return count == 0 ? false : true;
    }

    //结束合同，定时任务使用
    @Transactional
    @Override
    public boolean end(Contract contract) {
        contract.setBreakDownReason("时间已到，系统结束");
        contract.setStatus(ContractConstant.Status.END.codeOf());
        contract.setStatusVal(ContractConstant.Status.END.valueOf());
        contractRepository.save(contract);
        return true;
    }


    @Override
    public boolean beginTeachRoll(Contract contract) {
//        if (contract.getStatus() == ContractConstant.Status.NORMAL.codeOf()
//                && contract.getPayStatus() ) {
        if (contract.getStatus() == ContractConstant.Status.NORMAL.codeOf()
                && contract.getPayStatus() == ContractConstant.PayStatus.PAID.codeOf()) {
            Clientele clientele = clienteleRepository.getOne(contract.getClienteleId());
            List<ContractProduct> productList = contractProductRepository.findByContractId(contract.getId());
            List<ProductDTO> productVoList = productList.stream().map(o -> ProductDTO.of(o)).collect(Collectors.toList());
            return teachCallService.activeChild(clientele.getId(), DateUtil.millisToDateTime(contract.getBeginDate().getTime(), "yyyy-MM-dd"), DateUtil.millisToDateTime(contract.getEndDate().getTime(), "yyyy-MM-dd"), ModelUtil.toJson(productVoList));
        }
        return true;
    }

    @Override
    public boolean endTeachRoll(Contract contract, String staffId) {

//        if (!contract.getPayStatus())
//            return true;
        if (StringUtils.isNotEmpty(staffId) && !StringUtils.equals("",staffId)){
            contract.setStaffId(staffId);
        }
        //如果已经生效合同，则减去教务系统早教对应数量
        if (contract.getPayStatus() != ContractConstant.PayStatus.PAID.codeOf())
            return true;

        //终止教务系统的学籍
        ContractStatusVo contractStatus = clienteleService.checkAllContractOver(contract.getClienteleId());
        if (!contractStatus.isHasContract()) {
            teachCallService.overAllNurseryContract(contract.getClienteleId(), contract.getBreakDownReason(), contract.getStaffId());
            teachCallService.overAllEarlyContract(contract.getClienteleId(), contract.getBreakDownReason(), contract.getStaffId());
        } else {
            if (contractStatus.isNurseryContractEnd())
                teachCallService.overAllNurseryContract(contract.getClienteleId(), contract.getBreakDownReason(), contract.getStaffId());
            if (contractStatus.isEarlyContractEnd())
                teachCallService.overAllEarlyContract(contract.getClienteleId(), contract.getBreakDownReason(), contract.getStaffId());
            else
                subtractEarlyCourse(contract.getId(), contract.getClienteleId(), contract.getBreakDownReason(), contract.getStaffId());
        }
        return true;
    }

    @Override
    public Long findByStatusAndPayStatus(String clienteleId, int status, int payStatus) {
        return contractNativeRepository.findByStatusAndPayStatus(clienteleId, status, payStatus);
    }

    @Override
    public PayVo getPayTotal(String productJson) {
        BigDecimal actualAmount = BigDecimal.ZERO.setScale(2, BigDecimal.ROUND_HALF_DOWN);;
        BigDecimal planAmount = BigDecimal.ZERO.setScale(2, BigDecimal.ROUND_HALF_DOWN);;
        if(StringUtils.isNotBlank(productJson) && !"[]".equals(productJson)){
            JavaType javaType = ModelUtil.objectMapper.getTypeFactory().constructParametricType(ArrayList.class, PayProductVo.class);
            try {
                List<PayProductVo> PayProductVos = ModelUtil.objectMapper.readValue(productJson, javaType);
                for (PayProductVo payProductVo : PayProductVos) {
                    Product product = productRepository.getOne(payProductVo.getProductId());
                    actualAmount = actualAmount.add(payProductVo.getActualUnit().multiply(new BigDecimal(payProductVo.getNum()).setScale(2, BigDecimal.ROUND_HALF_DOWN)));     //实际总价格=实际单价*数量
                    planAmount = planAmount.add(product.getStandardAmount().multiply(new BigDecimal(payProductVo.getNum()).setScale(2, BigDecimal.ROUND_HALF_DOWN)));       //理论总价格=理论单价*数量
                }
            } catch (IOException e) {
                e.printStackTrace();
                throw  new BusinessException("数据格式错误");
            }
        }
        double discount = 0.d;
        if(actualAmount.doubleValue() !=0 && planAmount.doubleValue() !=0 ){
            discount= 1-actualAmount.doubleValue()/planAmount.doubleValue();
        }
        PayVo payVo = PayVo.of(actualAmount,ModelUtil.remainTwoPoint(discount));
        return payVo;
    }
    
    @Override
    public boolean checkConstractCode(String areaId,String contractCode) {
    	List<ContractVo> list = contractNativeRepository.checkContractCode(areaId,contractCode);
    	if(list.size()>0) {
    		return false;
    		
    	}else {
    		return true;
    	}
        
    }

	@Override
	public List<ContractVo> findListByClienteleId(String areaId, String clienteleId) {
		
		List<ContractVo> list = new ArrayList<ContractVo>();
		
		if(!StringUtils.isBlank(clienteleId)) {
			 list = contractNativeRepository.findListByClienteleId(areaId, clienteleId);
			 for(ContractVo cv : list) {
				 List<ContractProductVo> contractProductVos = contractProductNativeRepository.findByContractId(cv.getId());
				 cv.setContractProducts(contractProductVos);
			 }
		}
		
		return list;
	}

	@Override
	public StatusResponse freezeContract(StaffDTO staff, String clienteleId, String contractId, String content) {
		Contract contract = contractRepository.getOne(contractId);
		if(contract.getStatus() == ContractConstant.Status.STOP.codeOf() || contract.getStatus() == ContractConstant.Status.END.codeOf()) {
			return StatusResponse.error("000503", "该合同已终止或已结束，无法被冻结！");
		}
		
		if(contract.getStatus() == ContractConstant.Status.FREEZE.codeOf()) {
			return StatusResponse.error("000505", "该合同已冻结！");
		}
		Clientele clientele = clienteleRepository.getOne(clienteleId);

		
		//客户添加合同那边的冻结日志
        saveOpreation(clienteleId,contractId,staff.getRealName(), staff.getId(),"在 " + DateUtil.dateToymd(new Date()) + "冻结了本合同 " + '\n' + " 冻结原因：" + content );
        
        //修改合同状态
        contract.setStatus(ContractConstant.Status.FREEZE.codeOf()); //已冻结
        contract.setStatusVal(ContractConstant.Status.FREEZE.valueOf());
        contractRepository.save(contract);
        
        //添加合同冻结记录
        saveFreezeRecord(contract, staff, clientele,content);
        
        //冻结未开始合同
        List<Contract> list = contractRepository.findByClienteleIdAndStatus(clienteleId, ContractConstant.Status.NON_START.codeOf());
        if(list.size()>0) {
        	for(Contract ct : list) {
        		if(!ct.getId().equals(contractId)) {
        			
        			//客户添加合同那边的冻结日志
        	        saveOpreation(clienteleId,ct.getId(), staff.getRealName(), staff.getId(),"在 " + DateUtil.dateToymd(new Date()) + "冻结了本合同 " + '\n' + " 冻结原因：" + content );
        	        
        	        //修改合同状态
        	        ct.setStatus(ContractConstant.Status.FREEZE.codeOf()); //已冻结
        	        ct.setStatusVal(ContractConstant.Status.FREEZE.valueOf());
        	        contractRepository.save(ct);
        	        
        	        //添加合同冻结记录
        	        saveFreezeRecord(ct, staff, clientele,content);
        		}
        	}
        }
        
        //删除宝宝和班级之间的关系 修改宝宝当前状态
        teachCallService.updateChildInfo(clientele.getAreaId(), clienteleId, clientele.getChildName(),true);
        
		return StatusResponse.success();
	}

	@Override
	public StatusResponse unfreezeContract(StaffDTO staff, String clienteleId, String contractId) {

		Contract contract = contractRepository.getOne(contractId);
		if(contract.getStatus() != ContractConstant.Status.FREEZE.codeOf()) {
			return StatusResponse.error("000504", "该合同不是已冻结合同！");
		}
		Clientele clientele = clienteleRepository.getOne(clienteleId);
		
		//添加冻结结束时间
		ContractFreeze cf = contractFreezeRepository.findByContractIdAndStatus(contractId, ContractFreezeConstant.Status.NORMAL.codeOf());
		
		//根据冻结记录的开始时间判断是否能解冻
		/*
		 * if(validateTime(cf.getFreezeBeginDate(),new Date())) { return
		 * StatusResponse.error("000506", "合同冻结七天之后才能解冻！"); }
		 */
		cf.setFreezeEndDate(new Date());
		cf.setStatus(ContractFreezeConstant.Status.COMPLETED.codeOf());
		ContractFreeze newCf = contractFreezeRepository.save(cf);
		
		//合同添加解冻日志
		saveOpreation(clienteleId,contractId, staff.getRealName(), staff.getId(),"在 " + DateUtil.dateToymd(new Date()) + "解冻了本合同. ");
        
        //添加合同修改时间日志
        saveOpreation(clienteleId,contractId, staff.getRealName(), staff.getId(),"在 " + DateUtil.dateToymd(new Date()) + "修改了本合同时间，原合同开始时间： "+DateUtil.dateToymd(contract.getBeginDate())+",结束时间："+DateUtil.dateToymd(contract.getEndDate()));
        
        //修改合同状态以及结束时间
        contract.setStatus(ContractConstant.Status.NORMAL.codeOf());
        contract.setStatusVal(ContractConstant.Status.NORMAL.valueOf());
        contract.setEndDate(new Date(contract.getEndDate().getTime()+(newCf.getFreezeEndDate().getTime()-newCf.getFreezeEndDate().getTime())));
        contractRepository.save(contract);
        
        //解冻其他合同并修改时间 记录日志
        List<Contract> list = contractRepository.findByClienteleIdAndStatus(clienteleId, ContractConstant.Status.FREEZE.codeOf());
        if(list.size()>0) {
        	for(Contract ct : list) {
            	if(!ct.getId().equals(contract.getId())) {
            		
            		//解冻日志
            		saveOpreation(clienteleId,ct.getId(), staff.getRealName(), staff.getId(),"在 " + DateUtil.dateToymd(new Date()) + "解冻了本合同. ");
            		
            		//添加合同修改时间日志
                    saveOpreation(clienteleId,ct.getId(), staff.getRealName(), staff.getId(),"在 " + DateUtil.dateToymd(new Date()) + "修改了本合同时间，原合同开始时间： "+DateUtil.dateToymd(ct.getBeginDate())+",结束时间："+DateUtil.dateToymd(ct.getEndDate()));
                    
                    //修改合同状态及时间
                    ct.setStatus(ContractConstant.Status.NON_START.codeOf());
                    ct.setStatusVal(ContractConstant.Status.NON_START.valueOf());
                    ct.setBeginDate(new Date(ct.getBeginDate().getTime()+(newCf.getFreezeEndDate().getTime()-newCf.getFreezeEndDate().getTime())));
                    ct.setEndDate(new Date(ct.getEndDate().getTime()+(newCf.getFreezeEndDate().getTime()-newCf.getFreezeEndDate().getTime())));
                    contractRepository.save(ct);
                    
                    //添加冻结结束时间
                    ContractFreeze otherCf = contractFreezeRepository.findByContractIdAndStatus(ct.getId(), ContractFreezeConstant.Status.NORMAL.codeOf());
                    otherCf.setFreezeEndDate(new Date());
                    otherCf.setStatus(ContractFreezeConstant.Status.COMPLETED.codeOf());
            		contractFreezeRepository.save(cf);
                                		
            	}
            }
        }
        
        //修改宝宝当前状态为正常
        teachCallService.updateChildInfo(clientele.getAreaId(), clienteleId, clientele.getChildName(),false);
        
		return StatusResponse.success();
	}
	
	private ContractHistory saveOpreation(String clienteleId,String contractId,String name,String staffId,String content) {
		
		ContractHistory contractHistory = new ContractHistory();
		contractHistory.setOperationType(OPERATE_CREATE);           
        contractHistory.setContent(content);
        contractHistory.setClienteleId(clienteleId);
        contractHistory.setStaffId(staffId);
        contractHistory.setStaffName(name);
        contractHistory.setContractId(contractId);
        
        return contractHistoryRepository.save(contractHistory);
        
	}
	
	private ContractFreeze saveFreezeRecord(Contract contract, StaffDTO baseInfo,Clientele clientele,String content) {
		
		ContractFreeze cf = new ContractFreeze();
        
		cf.setCreated(baseInfo.getId());
        cf.setCreateTime(new Date());
        cf.setDeleted(0);
        cf.setAreaId(baseInfo.getAreaId());
        cf.setClienteleId(clientele.getId());
        cf.setClienteleName(clientele.getName());
        cf.setContractId(contract.getId());
        cf.setContractBeginDate(contract.getBeginDate());
        cf.setContractEndDate(contract.getEndDate());
        cf.setFreezeBeginDate(new Date());
        cf.setContent(content);
        cf.setStatus(ContractFreezeConstant.Status.NORMAL.codeOf());
        
        return contractFreezeRepository.save(cf);
        
	}
	
	private boolean validateTime(Date begin,Date end) {
		long week = (long)60*60*24*7*1000;
		if(week>(end.getTime()-begin.getTime())) {
			return true;
		}else {
			return false;
		}
				
	}

    @Override
    public Contract createContract(StaffDTO staff, Clientele clientele,String name, String orderNO,
                                    Date beginDate, Date endDate,
                                   BigDecimal totalAmount, String productRecords){

        //创建合同
        Contract contract = new Contract();
        contract.setAreaId(staff.getAreaId());

        contract.setName(name + "-" + clientele.getName() + "-" + clientele.getSysChildName());

        contract.setCode(orderNO);

        contract.setBeginDate(beginDate);
        contract.setEndDate(endDate);

        //设置成待线上支付
        contract.setPayType(ContractConstant.PayType.ONLINE.codeOf());
        contract.setPayTypeVal(ContractConstant.PayType.ONLINE.valueOf());

        contract.setStatus(4); //0：未开始 1。正常， 2：已终止, 3：已结束  4:待补款
        contract.setStatusVal("待补款");

        contract.setSignDate(new Date());
        contract.setTotalAmount(totalAmount);

        contract.setClienteleId(clientele.getId());

        Contract saveContract = save(staff, contract, productRecords);
        return saveContract;
    }
}
